home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / Comm / AmiTCP30b2.lha / src / amitcp / kern / amiga_cstat.c < prev    next >
C/C++ Source or Header  |  1994-02-03  |  15KB  |  576 lines

  1. RCS_ID_C="$Id: amiga_cstat.c,v 3.1 1994/02/03 03:59:36 ppessi Exp $";
  2. /*
  3.  * Copyright (c) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
  4.  *                    Helsinki University of Technology, Finland.
  5.  *                    All rights reserved.
  6.  *
  7.  * HISTORY
  8.  * $Log: amiga_cstat.c,v $
  9.  * Revision 3.1  1994/02/03  03:59:36  ppessi
  10.  * Changed the format of network interface names
  11.  *
  12.  * Revision 1.23  1994/01/18  02:29:17  jraja
  13.  * Added rexx_gethostname() and rexx_sethostname() functions.
  14.  *
  15.  * Revision 1.22  1993/12/31  01:23:24  ppessi
  16.  * Fixed netmask handling.
  17.  *
  18.  * Revision 1.21  1993/11/06  23:51:22  ppessi
  19.  * Added Berkeley licence. Added route tree printing routines.
  20.  * Changed some allocation routines.
  21.  *
  22.  */
  23.  
  24. /*
  25.  * Copyright (c) 1983, 1988 Regents of the University of California.
  26.  * All rights reserved.
  27.  *
  28.  * Redistribution and use in source and binary forms, with or without
  29.  * modification, are permitted provided that the following conditions
  30.  * are met:
  31.  * 1. Redistributions of source code must retain the above copyright
  32.  *    notice, this list of conditions and the following disclaimer.
  33.  * 2. Redistributions in binary form must reproduce the above copyright
  34.  *    notice, this list of conditions and the following disclaimer in the
  35.  *    documentation and/or other materials provided with the distribution.
  36.  * 3. All advertising materials mentioning features or use of this software
  37.  *    must display the following acknowledgement:
  38.  *    This product includes software developed by the University of
  39.  *    California, Berkeley and its contributors.
  40.  * 4. Neither the name of the University nor the names of its contributors
  41.  *    may be used to endorse or promote products derived from this software
  42.  *    without specific prior written permission.
  43.  *
  44.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  45.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  46.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  47.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  48.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  49.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  50.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  51.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  52.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  53.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  54.  * SUCH DAMAGE.
  55.  */
  56.  
  57. #include <conf.h>
  58.  
  59. #include <sys/param.h>
  60. #include <sys/systm.h>
  61. #include <sys/socket.h>
  62. #include <sys/socketvar.h>
  63. #include <sys/synch.h>
  64. #include <sys/malloc.h>
  65. #include <sys/syslog.h>
  66.  
  67. #include <kern/amiga_includes.h>
  68. #include <kern/amiga_rexx.h>
  69. #include <kern/amiga_config.h>
  70.  
  71. #include <dos/rdargs.h>
  72.  
  73. #if __SASC
  74. #include <proto/dos.h>
  75. #elif __GNUC__
  76. #include <inline/dos.h>
  77. #endif
  78.  
  79. #include <net/route.h>
  80. #include <netinet/in_systm.h>
  81. #include <netinet/in.h>
  82. #include <netinet/ip.h>
  83. #include <netinet/in_pcb.h>
  84. #include <netinet/ip_var.h>
  85. #include <netinet/ip_icmp.h>
  86. #include <netinet/icmp_var.h>
  87. #include <netinet/tcp.h>
  88. #include <netinet/tcp_timer.h>
  89. #include <netinet/tcp_var.h>
  90. #include <netinet/udp.h>
  91. #include <netinet/udp_var.h>
  92.  
  93. #include <api/apicalls.h>
  94.  
  95. long count = 0;
  96.  
  97. int
  98. ultoa(unsigned long ul,char *buffer)
  99. {
  100.   static char buf[10];
  101.   char *p;
  102.   int len;
  103.  
  104.   p = buf;
  105.   *p='\0';
  106.  
  107.   do {
  108.     *++p = (ul % 10)+'0';
  109.   } while (ul /= 10);
  110.  
  111.   len = p - buf;
  112.  
  113.   while (*buffer++ = *p--)
  114.     ;
  115.   return(len);
  116. }
  117.  
  118. int
  119. ltoa(long l, char *buffer)
  120. {
  121.   int len=0;
  122.  
  123.   if(l<0){
  124.     *buffer++='-';
  125.     l=-l;
  126.     len++;
  127.   }
  128.  return (len + ultoa((unsigned long)l, buffer));
  129. }
  130.  
  131. /*
  132.  * Allocate big enough buffer for reply
  133.  */
  134. LONG
  135. CS_Alloc(struct CSource *reply, size_t size)
  136. {
  137.   /* do we have enough space? */
  138.   if (reply->CS_Length < size) {
  139.     char *buffer;
  140.     if ((buffer = bsd_malloc(size, M_TEMP, 0)) == NULL){
  141.       return 0;
  142.     }
  143.     /*
  144.      * Old buffer will be freed by caller
  145.      */
  146.     reply->CS_Buffer = buffer;
  147.     reply->CS_Length = size;
  148.   }
  149.  
  150.   return 1;
  151. }
  152.  
  153. /*
  154.  * getsockets(): a reply statics for all sockets
  155.  *
  156.  */
  157. struct printsocket {
  158.   struct in_addr  inp_faddr;    /* u_long, far addr */
  159.   u_short         inp_fport;
  160.   struct in_addr  inp_laddr;    /* u_long, local addr */
  161.   u_short         inp_lport;
  162.   short           so_type;    /* SOCK_STREAM, _DGRAM... */
  163.   u_short         so_rcv_sb_cc;    /* Recv queue size */
  164.   u_short         so_snd_sb_cc;    /* Send queue */
  165.   short           inp_ppcb_t_state; /* State of TCP connection */
  166. };
  167.  
  168. LONG
  169. getsockets(struct CSource *args, UBYTE **errstrp, struct CSource *res)
  170. {
  171.   int i, count = 0;
  172.   struct inpcb *pcb;
  173.   struct printsocket *pps, *mem;
  174.   spl_t s = splnet();        /* Critical section starts here */
  175.  
  176.   /* Count number of connections */
  177.   for(pcb = udb.inp_next; pcb != &udb ; pcb = pcb->inp_next)
  178.     ++count;
  179.   for(pcb = tcb.inp_next; pcb != &tcb ; pcb = pcb->inp_next)
  180.     ++count;
  181.  
  182.   if (count == 0) {        /* return now if nothing to print */
  183.     splx(s);
  184.     return RETURN_OK;
  185.   }
  186.  
  187.   /* Allocate memory */
  188.   mem = (struct printsocket *)
  189.     bsd_malloc(sizeof(struct printsocket) * (count), M_TEMP, 0);
  190.  
  191.   if (mem == NULL) {
  192.     splx(s);
  193.     *errstrp = ERR_MEMORY;
  194.     return RETURN_FAIL;
  195.   }
  196.  
  197.   /* Proto recv-q send-q laddr lport faddr fport state */
  198.   /*  1   1   4  1   4  1  8  1  4  1   8 1   4 1 1   1 =  42 chars */
  199. #define STATLEN 42
  200.   if (!CS_Alloc(res, STATLEN * count + 1)) {
  201.     /* Allocation failed, free printsocket memory */
  202.     splx(s);
  203.     bsd_free(mem, M_TEMP);
  204.     *errstrp = ERR_MEMORY;
  205.     return RETURN_FAIL;
  206.   }
  207.  
  208.   /* Copy information, TCP first.. */
  209.   for(pcb = tcb.inp_next, pps = mem; pcb != &tcb; pcb = pcb->inp_next, ++pps){
  210.     pps->inp_faddr = pcb->inp_faddr;
  211.     pps->inp_fport = pcb->inp_fport;
  212.     pps->inp_laddr = pcb->inp_laddr;
  213.     pps->inp_lport = pcb->inp_lport;
  214.     pps->so_type = pcb->inp_socket->so_type;
  215.     pps->so_rcv_sb_cc = pcb->inp_socket->so_rcv.sb_cc;
  216.     pps->so_snd_sb_cc = pcb->inp_socket->so_snd.sb_cc;
  217.     pps->inp_ppcb_t_state = ((struct tcpcb *)(pcb->inp_ppcb))->t_state;
  218.   }
  219.   /* ...then UDP */
  220.   for(pcb = udb.inp_next; pcb != &udb; pcb = pcb->inp_next, ++pps){
  221.     pps->inp_faddr = pcb->inp_faddr;
  222.     pps->inp_fport = pcb->inp_fport;
  223.     pps->inp_laddr = pcb->inp_laddr;
  224.     pps->inp_lport = pcb->inp_lport;
  225.     pps->so_type = pcb->inp_socket->so_type;
  226.     pps->so_rcv_sb_cc = pcb->inp_socket->so_rcv.sb_cc;
  227.     pps->so_snd_sb_cc = pcb->inp_socket->so_snd.sb_cc;
  228.     pps->inp_ppcb_t_state = 0;    /* NO state for UDP */
  229.   }
  230.  
  231.   splx(s);            /* Critical section completed now */
  232.  
  233.   /*
  234.    * Print all socket entries
  235.    */
  236.   for(i = 0; i < count; i++)
  237.     csprintf(res, "%lc %04lx %04lx %08lx %04lx %08lx %04lx %1lx%s",
  238.          mem[i].so_type == SOCK_STREAM ? 't': 'u',
  239.          mem[i].so_rcv_sb_cc, mem[i].so_snd_sb_cc,
  240.          mem[i].inp_laddr.s_addr, mem[i].inp_lport,
  241.          mem[i].inp_faddr.s_addr, mem[i].inp_fport,
  242.          mem[i].inp_ppcb_t_state,
  243.          (i < count - 1) ? " " : "");
  244.  
  245. #if DIAGNOSTIC            /* check for overrun */
  246.   if (res->CS_CurChr >= res->CS_Length)
  247.     log(LOG_ERR, "getsockets(): buffer overwritten by %ld bytes\n",
  248.     res->CS_CurChr - res->CS_Length + 1);
  249. #endif
  250.  
  251.   /*
  252.    * free mem
  253.    */
  254.   bsd_free(mem, M_TEMP);
  255.  
  256.   return RETURN_OK;
  257. }
  258.  
  259. /*
  260.  * Get ICMP history profiles
  261.  */
  262. #include <netinet/icmp_var.h>
  263. #include <netinet/ip_icmp.h>
  264.  
  265. LONG 
  266. read_icmphist(struct CSource *args, UBYTE **errstrp, struct CSource *res)
  267. {
  268.   int i;
  269.   UBYTE *p = res->CS_Buffer;
  270.  
  271.   for(i = 0;i <= ICMP_MAXTYPE; i++){
  272.     p += ultoa(icmpstat.icps_outhist[i], p);
  273.     *p++=' ';
  274.   }
  275.  
  276.   for(i = 0;i <= ICMP_MAXTYPE; i++){
  277.     p += ultoa(icmpstat.icps_inhist[i], p);
  278.     *p++ = ' ';
  279.   }
  280.   *--p = '\0';
  281.  
  282.   res->CS_CurChr = p - res->CS_Buffer;
  283.   return RETURN_OK;
  284. }
  285.  
  286. /*
  287.  * Get routing tables
  288.  */
  289. #include <net/route.h>
  290. #include <net/if.h>
  291.  
  292. #define DB(x) ;
  293.  
  294. /* Address families supported */
  295. extern STRPTR KW_Protocols;
  296.  
  297. /* What is stored in the route entry */
  298. #define NORMAL 0
  299. #define MASK   1
  300. #define DUPED  2
  301.  
  302. /* Our recursion depth in route tree. 32 is # of bits in IP address */
  303. /* Other protocols may require deeper stack */
  304. #define MAX_ROUTE_TREE_DEPTH 32
  305.  
  306. struct printroute {
  307.   struct sockaddr pr_dest;
  308.   struct sockaddr pr_via;
  309.   u_long          pr_use;
  310.   struct ifnet   *pr_ifp;
  311.   short           pr_refcnt;
  312.   u_short         pr_flags;
  313.   u_short         pr_what;
  314. };
  315.  
  316. static void cstat_rtentry(struct rtentry *rt, struct printroute *pr);
  317. static void cstat_maskentry(struct radix_node *rn, struct printroute *pr);
  318. static int  cstat_rtree(struct radix_node *rn, struct printroute *pr, int);
  319. static void cstat_rtflags(struct CSource *, const char *, register int);
  320.  
  321. LONG
  322. getroutes(struct CSource *args, UBYTE **errstrp, struct CSource *res)
  323. {
  324.   UBYTE Buffer[KEYWORDLEN];
  325.   int af, newroutes, routes = 0;
  326.   struct radix_node_head *rnh;
  327.   struct printroute *mem, *pr;
  328.   spl_t s;
  329.  
  330.   /*
  331.    * Parse address family
  332.    *
  333.    * Match the  against the template. The af is the index of
  334.    * the matching keyword, if one is found.
  335.    */
  336.   if (ReadItem(Buffer, sizeof(Buffer), args) <= 0) {
  337.     *errstrp = ERR_SYNTAX;
  338.     return RETURN_ERROR;
  339.   }
  340.   if ((af = FindArg(KW_Protocols, Buffer)) < 0) {
  341.     res->CS_CurChr = 0;
  342.     csprintf(res, ERR_ILLEGAL_VAR, "getroutes", Buffer);
  343.     *errstrp = res->CS_Buffer;
  344.     return RETURN_WARN;
  345.   }
  346.  
  347.   DB(log(LOG_DEBUG, "getroutes: getting routes for protocol %s (%ld)",
  348.      Buffer, af));
  349.  
  350.   s = splnet();            /*                         Critical section */
  351.  
  352.   /* Count entries in tables */
  353.   for (rnh = radix_node_head; rnh ; rnh = rnh->rnh_next) {
  354.     if (af == AF_UNSPEC || af == rnh->rnh_af) {
  355.       newroutes = cstat_rtree(rnh->rnh_treetop, NULL, rnh->rnh_af != AF_UNSPEC);
  356.       if (newroutes < 0) {
  357.     splx(s);
  358.     *errstrp = (UBYTE *)"Route tree overflow.\n";
  359.     return RETURN_FAIL;
  360.       }
  361.       routes += newroutes;
  362.     }
  363.   }
  364.  
  365.   DB(log(LOG_DEBUG, "getroutes: found %ld routes", routes));
  366.  
  367.   /* Allocate memory for entries */
  368.   pr = mem = (struct printroute *)
  369.     bsd_malloc(sizeof(struct printroute) * (routes), M_TEMP, 0);
  370.  
  371.   if (mem == NULL) {
  372.     splx(s);
  373.     *errstrp = ERR_MEMORY;
  374.     return RETURN_FAIL;
  375.   }
  376.  
  377.   /* Fill in printroute table */
  378.   for (rnh = radix_node_head; rnh ; rnh = rnh->rnh_next) {
  379.     if (af == AF_UNSPEC || af == rnh->rnh_af) {
  380.       pr += cstat_rtree(rnh->rnh_treetop, pr, rnh->rnh_af != AF_UNSPEC);
  381. #if DIAGNOSTIC
  382.       if (pr > mem + routes) {
  383.     const UBYTE *msg = "cstat_rtree(): found more entries than counted!\n";
  384.     splx(s);
  385.     bsd_free(mem, M_TEMP);
  386.     log(LOG_ERR, msg);
  387.     *errstrp = (UBYTE *)msg;
  388.     return RETURN_FAIL;
  389.       }
  390. #endif
  391.     }
  392.   }
  393.   splx(s);            /*                  End of critical section */
  394.  
  395.   /* Reply line has format
  396.    * protocol route gateway flags refcount used device/unit + separation
  397.    * 2  +     8  +  8  +    4  +  4  +     8  + 32  +  10  + 10  = 90 chars
  398.    */
  399.   if (!CS_Alloc(res, 90 * routes)) {
  400.     /* Allocation failed, free printroute memory */
  401.     bsd_free(mem, M_TEMP);
  402.     *errstrp = ERR_MEMORY;
  403.     return RETURN_FAIL;
  404.   }
  405.  
  406.   /* cstat_rtree_print */
  407.   for (pr = mem; routes-- > 0 ; pr++) {
  408.     csprintf(res, "%02lx %08lx %08lx ",
  409.          pr->pr_dest.sa_family,
  410.          ((struct sockaddr_in *)&pr->pr_dest)->sin_addr.s_addr,
  411.          ((struct sockaddr_in *)&pr->pr_via)->sin_addr.s_addr);
  412.     cstat_rtflags(res, "%-8.8s ", pr->pr_flags);
  413.     csprintf(res, "%04lx %08lx ", pr->pr_refcnt, pr->pr_use);
  414.     if (pr->pr_ifp) {
  415.       csprintf(res, "%s%ld ", pr->pr_ifp->if_name, pr->pr_ifp->if_unit);
  416.     } else {
  417.       csprintf(res, "none ");
  418.     }
  419.   }
  420.  
  421.   /* free printsocket structures */
  422.   bsd_free(mem, M_TEMP);
  423.  
  424.   return RETURN_OK;
  425. }
  426.  
  427. /*
  428.  * cstat_rtree(): get a route tree to a table
  429.  */
  430. static int
  431. cstat_rtree(struct radix_node *rn, struct printroute *pr, int do_rtent)
  432. {
  433.   short routes = 0;
  434.   short stack_pointer = 0;
  435.   struct radix_node *stack[MAX_ROUTE_TREE_DEPTH];
  436.  
  437.  again:
  438.   if (rn->rn_b < 0) {
  439.     if ((rn->rn_flags & RNF_ROOT) == 0) {
  440.       if (pr) {
  441.     if (do_rtent)
  442.       cstat_rtentry((struct rtentry*)rn, pr);
  443.     else
  444.       cstat_maskentry(rn, pr);
  445.     pr++;
  446.       }
  447.       routes++;
  448.     }
  449.     if (rn = rn->rn_dupedkey)
  450.       goto again;
  451.   } else {
  452.     if (rn->rn_r) {
  453.       if (stack_pointer >= MAX_ROUTE_TREE_DEPTH - 1)
  454.     return -1;
  455.       stack[stack_pointer++] = rn->rn_r;
  456.     }
  457.     /* tail recursion removal */
  458.     if (rn = rn->rn_l) {
  459.       goto again;
  460.     }
  461.   }
  462.  
  463.   /* recursion removal */
  464.   if (stack_pointer-- > 0) {
  465.     rn = stack[stack_pointer];
  466.     goto again;
  467.   }
  468.  
  469.   DB(log(LOG_DEBUG, "rtree: found %ld routes", routes));
  470.   return routes;
  471. }
  472.  
  473. /*
  474.  * Copy rtentry into printroute
  475.  *      assumes that rtentry and pr are valid
  476.  */
  477. static void
  478. cstat_rtentry(struct rtentry *rt, struct printroute *pr)
  479. {
  480.   /* These should allow variable sized sockaddrs */
  481.   bcopy(rt_key(rt), &pr->pr_dest, sizeof(pr->pr_dest));
  482.   bcopy(rt->rt_gateway, &pr->pr_via, sizeof(pr->pr_via));
  483.  
  484.   /* */
  485.   pr->pr_use    = rt->rt_use;
  486.   pr->pr_refcnt = rt->rt_refcnt;
  487.   pr->pr_ifp    = rt->rt_ifp;
  488.   pr->pr_flags  = rt->rt_flags;
  489.   if (rt->rt_nodes->rn_dupedkey)
  490.     pr->pr_what = DUPED;
  491.   else
  492.     pr->pr_what = NORMAL;
  493. }
  494.  
  495. /*
  496.  * Copy netmask into printroute
  497.  *      assumes that rn and pr are valid
  498.  */
  499. static void
  500. cstat_maskentry(struct radix_node *rn, struct printroute *pr)
  501. {
  502.   /* These should allow variable sized sockaddrs */
  503.   bcopy((struct sockaddr *)rn->rn_key, &pr->pr_dest, sizeof(pr->pr_dest));
  504.   bzero(&pr->pr_via, sizeof(pr->pr_via));
  505.  
  506.   pr->pr_use    = 0;
  507.   pr->pr_refcnt = 0;
  508.   pr->pr_ifp    = NULL;
  509.   pr->pr_flags  = 0;
  510.   pr->pr_what   = MASK;
  511. }
  512.  
  513. /*
  514.  * Definitions for showing gateway flags.
  515.  */
  516. struct bits {
  517.     short    b_mask;
  518.     char    b_val;
  519. } bits[] = {
  520.     { RTF_UP,    'U' },
  521.     { RTF_GATEWAY,    'G' },
  522.     { RTF_HOST,    'H' },
  523.     { RTF_DYNAMIC,    'D' },
  524.     { RTF_MODIFIED,    'M' },
  525.     { RTF_CLONING,    'C' },
  526.     { RTF_XRESOLVE,    'X' },
  527.     { RTF_LLINFO,    'L' },
  528.     { RTF_REJECT,    'R' },
  529.     { 0 }
  530. };
  531.  
  532. static void
  533. cstat_rtflags(struct CSource *res, const char *format, register int f)
  534. {
  535.   char name[33], *flags;
  536.   register struct bits *p = bits;
  537.   for (flags = name; p->b_mask; p++)
  538.     if (p->b_mask & f)
  539.       *flags++ = p->b_val;
  540.   *flags = '\0';
  541.   if (name[0] != '\0') {
  542.     csprintf(res, format, name);
  543.   } else {
  544.     /* Empty string may confuse parsers */
  545.     csprintf(res, format, "\"\"");
  546.   }
  547. }
  548.  
  549. extern char *host_name;
  550. extern size_t host_namelen;
  551. extern int sethostname(const char * name, size_t namelen);
  552. extern struct Library *SocketBase; /* base opened by NETTRACE */
  553.  
  554. LONG
  555. rexx_gethostname(struct CSource *args, UBYTE **errstrp, struct CSource *res)
  556. {
  557.   gethostname((struct SocketBase *)SocketBase, CURRENT(res), SPACE(res));
  558.   res->CS_CurChr += strlen(CURRENT(res));
  559.  
  560.   return RETURN_OK;
  561. }
  562.  
  563. LONG
  564. rexx_sethostname(struct CSource *args, UBYTE **errstrp, struct CSource *res)
  565. {
  566.   char Buffer[MAXHOSTNAMELEN+1];
  567.  
  568.   if (ReadItem(Buffer, sizeof(Buffer), args) <= 0) {
  569.     *errstrp = ERR_SYNTAX;
  570.     return RETURN_ERROR;
  571.   }
  572.  
  573.   sethostname(Buffer, sizeof(Buffer));
  574.   return RETURN_OK;
  575. }
  576.